import call_counter
import wood
import trigonometric
import extend_powell_singular
import tr_solver
import ls_solver
import optimizer_util

EPSILON = 1e-8
MAX_ITER = 1000
INIT_TR_RADIUS = 0.1
MAX_TR_RADIUS = 100


def create_ls_solver():
    def solve(f, g, h, x0):
        return ls_solver.solve(f, g, h, x0, EPSILON, MAX_ITER)

    return solve


def create_tr_solver(sub_solve):
    def solve(f, g, h, x0):
        return tr_solver.solve(f, g, h, x0, EPSILON, MAX_ITER, INIT_TR_RADIUS, MAX_TR_RADIUS, sub_solve)

    return solve


METHODS = {
    'Hebden': create_tr_solver(tr_solver.hebden),
    'MoreSorensen': create_tr_solver(tr_solver.more_sorensen),
    'Subspace': create_tr_solver(tr_solver.subspace),
    'LineSearch': create_ls_solver()
}

OBJECTIVES = {
    'wood': wood.create(),
    'psf20': extend_powell_singular.create(20),
    'psf100': extend_powell_singular.create(100),
    'tri20': trigonometric.create(20),
    'tri100': trigonometric.create(100),
}


def benchmark_all():
    for obj_name, (x0, f0, g0, h0) in OBJECTIVES.items():
        print("================current objective: " + obj_name + "=====================")
        for m_name, optimize in METHODS.items():
            f, g, h, fc, gc, hc = call_counter.wrap(f0, g0, h0)
            x, it_n, it_s, hard_c, msg = optimize(f, g, h, x0)
            optimizer_util.show_result(f0, g0, x, it_n, it_s, hard_c, msg, fc, gc, hc, m_name)
        print()


def main():
    benchmark_all()


if __name__ == '__main__':
    main()
